import { forwardRef, useImperativeHandle, useState } from 'react'
import type { LineDataType, RainbowDataType, SettingType } from './interface'
import { transformData } from './util'

const GenerateRainbow = forwardRef((props, ref) => {
    // 画布大小
    let [canvasSize, setCanvasSize] = useState({ width: 1920, height: 1080 })
    // 线条数据
    let [postList, setPostList] = useState<LineDataType[]>([
        {
            post: '子女',
            color: '#9B92FF',
            data: [],
        },
        {
            post: '学生',
            color: '#829DFF',
            data: [],
        },
        {
            post: '休闲者',
            color: '#8CE2FB',
            data: [],
        },
        {
            post: '公民',
            color: '#A4FABA',
            data: [],
        },
        {
            post: '工作者',
            color: '#DDD877',
            data: [],
        },
        {
            post: '持家者',
            color: '#FF7EA5',
            data: [],
        },
    ])
    // 阶段提示文案信息
    const stageData = [
        { title: '成长阶段', x: 211, y: 772 },
        { title: '探索阶段', x: 280, y: 553 },
        { title: '建立阶段', x: 536, y: 278 },
        { title: '维持阶段', x: 920, y: 174 },
        { title: '退出阶段', x: 1468, y: 420 },
    ]
    // 最小线条半径
    let radius = 240
    // 线条间隔
    let radiusDelta = 60
    // 年龄平分角度
    let parts = 1 / 100
    // 画线条的宽度
    let activeLineWidth = 16
    // 线条的宽度
    let lineWidth = 2
    const getVw = (size: number): number => {
        return (size / 1920) * canvasSize.width
    }
    const getVh = (size: number): number => {
        return (size / 1080) * canvasSize.height
    }
    const getRadius = (): number => {
        return getVw(radius)
    }
    const getRadiusDelta = (): number => {
        return getVw(radiusDelta)
    }
    const getActiveLineWidth = (): number => {
        return getVw(activeLineWidth)
    }
    // 获取字体大小
    const getFontSize = (fontSize: number): string => {
        // 这个是根据页面大小来缩放的，但是这里的canvas宽高是固定死的所以不需要
        // return `${(fontSize / 1920) * 100}vw`
        return `${fontSize}px`
    }
    const getCircleRadius = (circle: number): number => {
        return getVw(radius) + getVw(radiusDelta) * circle
    }
    // 绘画更新
    const draw = () => {
        const cvEl = document.getElementById('generate_canvas') as HTMLCanvasElement
        if (cvEl) {
            // 1.
            const ctx = cvEl.getContext('2d') as CanvasRenderingContext2D
            let dpr = window.devicePixelRatio
            const w = cvEl.clientWidth
            const h = cvEl.clientHeight
            if (dpr) {
                cvEl.width = w * dpr
                cvEl.height = h * dpr
                ctx.scale(dpr, dpr)
            }
            // 清除画布
            ctx.clearRect(0, 0, w, h)
            // 绘制背景图
            ctx.save()
            ctx.fillStyle = '#31374e'
            ctx.fillRect(0, 0, w, h)
            ctx.restore()
            let paintX = w / 2
            let paintY = getVh(1080) - getVh(174)
            for (let i = 0; i < postList.length; i++) {
                ctx.strokeStyle = postList[i].color
                ctx.lineWidth = lineWidth
                ctx.lineCap = 'round'
                ctx.beginPath()
                const lineRadius = getRadius() + getRadiusDelta() * i
                ctx.arc(paintX, paintY, lineRadius, 0, Math.PI, true)
                ctx.stroke()
                // 画线条
                const data = postList[i].data
                for (let j = 0; j < data.length; j++) {
                    ctx.strokeStyle = postList[i].color
                    ctx.lineWidth = (activeLineWidth / 1080) * h
                    ctx.lineCap = 'butt'
                    ctx.beginPath()
                    // if ((data[j].minAngle === 0 && data[j].maxAngle === 0) || currentArc.radius === 0) {
                    if (data[j].minAngle === 0 && data[j].maxAngle === 0) {
                        let end = 1 + parts * data[j].min
                        let endAngle = Math.PI * end
                        if (endAngle < Math.PI) {
                            endAngle = Math.PI
                        }
                        data[j].minAngle = endAngle
                        let start = 1 + parts * data[j].max
                        let startAngle = Math.PI * start
                        if (startAngle > 2 * Math.PI) {
                            startAngle = 2 * Math.PI
                        }
                        data[j].maxAngle = startAngle
                    }

                    let dataLineRadius = getVw(radius) + getVw(radiusDelta) * i + getActiveLineWidth() / 2 + getActiveLineWidth() * (data[j].score - 1)
                    ctx.arc(paintX, paintY, dataLineRadius, data[j].maxAngle, data[j].minAngle, true)
                    ctx.stroke()
                }

                // 线条标题
                if (postList[i].post) {
                    ctx.fillStyle = '#fafbfb'
                    ctx.textAlign = 'center'
                    ctx.font = `${getFontSize(20)} PingFangSC`
                    ctx.fillText(postList[i].post, paintX, paintY - lineRadius - getActiveLineWidth())
                }
            }

            ctx.strokeStyle = '#ff7ea5'
            ctx.lineWidth = lineWidth
            ctx.lineCap = 'round'
            ctx.beginPath()
            ctx.arc(paintX, paintY, getCircleRadius(6), 0, Math.PI, true)
            ctx.stroke()

            ctx.strokeStyle = '#ffe496'
            ctx.lineWidth = lineWidth
            ctx.lineCap = 'round'
            ctx.beginPath()
            let circle7Radius = getRadius() + getRadiusDelta() * 7
            let circle7Angle = getVh(80) / circle7Radius / Math.PI
            ctx.arc(paintX, paintY, getRadius() + getRadiusDelta() * 7, -circle7Angle, Math.PI + circle7Angle, true)
            ctx.stroke()

            ctx.strokeStyle = '#ffe496'
            ctx.lineWidth = lineWidth
            ctx.lineCap = 'round'
            ctx.beginPath()
            let circle8Radius = getRadius() + getRadiusDelta() * 8
            let circle8Angle = getVh(80) / circle8Radius / Math.PI
            ctx.arc(paintX, paintY, circle8Radius, -circle8Angle, Math.PI + circle8Angle, true)
            ctx.stroke()

            // 更新页面相关标题
            ctx.fillStyle = '#ffffff'
            ctx.textAlign = 'center'
            ctx.font = `${getFontSize(28)} PingFangSC`
            ctx.fillText('个人决定因素', paintX, paintY - getVh(80))

            ctx.fillStyle = '#ffffff'
            ctx.textAlign = 'left'
            ctx.font = `${getFontSize(18)} PingFangSC`
            ctx.fillText('心理的', paintX + getVw(8), paintY - getVh(47))

            ctx.fillStyle = '#ffffff'
            ctx.textAlign = 'right'
            ctx.font = `${getFontSize(18)} PingFangSC`
            ctx.fillText('生物的', paintX - getVw(8), paintY - getVh(47))

            ctx.fillStyle = '#ffffff'
            ctx.textAlign = 'left'
            ctx.font = `${getFontSize(28)} PingFangSC`
            ctx.fillText('环境决定因素', getVw(1392), getVh(226))

            ctx.fillStyle = '#ffffff'
            ctx.textAlign = 'left'
            ctx.font = `${getFontSize(18)} PingFangSC`
            ctx.fillText('历史的 社会经济的', getVw(1392), getVh(274))

            let liveTitleRadius = getRadius() + getRadiusDelta() * 6
            ctx.fillStyle = '#FED04B'
            ctx.textAlign = 'right'
            ctx.font = `${getFontSize(20)} PingFangSC`
            ctx.fillText('生命阶段与年龄', w / 2 - liveTitleRadius - getVw(20), paintY)
            ctx.fillStyle = '#FED04B'
            ctx.textAlign = 'left'
            ctx.font = `${getFontSize(20)} PingFangSC`
            ctx.fillText('年龄与生命阶段', w / 2 + liveTitleRadius + getVw(20), paintY)

            for (let k = 0; k < 20; k++) {
                ctx.fillStyle = '#FED04B'
                ctx.textAlign = 'center'
                ctx.font = `${getFontSize(20)} PingFangSC`
                let topHeight = getVh(1080) - getVh(174)
                let ageLineRadius = getRadius() + getRadiusDelta() * 6 + getVw(20)
                let num = (Math.PI / 20) * k
                let numY = Math.sin(num) * ageLineRadius
                let numX = Math.cos(num) * ageLineRadius
                if (k > 0) {
                    ctx.fillText(`${(20 - k) * 5}`, w / 2 + numX, topHeight - numY)
                }
            }

            // 阶段文案
            for (let m = 0; m < stageData.length; m++) {
                const stageDatum = stageData[m]
                let x = getVw(stageDatum.x)
                let y = getVh(stageDatum.y + 21)
                ctx.clearRect(x - getVw(4), y - getVw(24), getVw(88), getVh(36))
                // 增加文字背景
                ctx.fillStyle = '#31374e'
                ctx.fillRect(x - getVw(4), y - getVw(24), getVw(88), getVh(36))
                // 文字颜色设置
                ctx.fillStyle = '#FFA175'
                ctx.textAlign = 'left'
                ctx.font = `${getFontSize(20)}`
                ctx.fillText(stageDatum.title, x, y)
            }
        }
    }
    /** 根据数据绘制彩虹图 */
    const accordDataToDraw = (originData: RainbowDataType[]) => {
        let data = transformData(originData)
        for (let i = 0; i < data.length; i++) {
            for (let j = 0; j < postList.length; j++) {
                if (postList[j].post === data[i].name) {
                    postList[j] = {
                        post: data[i].name,
                        color: postList[j].color,
                        data: data[i].settings.map((val: SettingType) => {
                            return {
                                min: parseFloat(val.age_start),
                                max: parseFloat(val.age_end),
                                minAngle: 0,
                                maxAngle: 0,
                                score: parseFloat(val.grade as string),
                            }
                        }),
                    }
                }
            }
        }
        setPostList(postList)
        draw()
    }
    /** 生成图片 */
    const getCanvasImage = () => {
        const canvas = document.getElementById('generate_canvas') as HTMLCanvasElement
        if (canvas) {
            const dataURL = canvas.toDataURL('image/png', 1)
            return dataURL
        }
    }

    useImperativeHandle(ref, () => {
        return {
            exportImage: (data: RainbowDataType[]) => {
                accordDataToDraw(data)
                return getCanvasImage()
            },
        }
    })

    return (
        <div style={{ position: 'relative', overflow: 'hidden' }}>
            <canvas id="generate_canvas" style={{ width: canvasSize.width, height: canvasSize.height, position: 'absolute', zIndex: -100 }} />
        </div>
    )
})
export default GenerateRainbow
